package toolkit

import (
	"bytes"
	"fmt"
	ose "os/exec"
	"path/filepath"
	"runtime"
	"strings"
	"time"
	"unicode"
)

type GOOS string

func (g GOOS) String() string {
	return string(g)
}

const (
	Windows GOOS = "windows"
	Linux   GOOS = "linux"
	Darwin  GOOS = "darwin"
	FreeBSD GOOS = "freebsd"
)

// GetGOOS 获取系统信息
func GetGOOS() GOOS {
	if runtime.GOOS == "windows" {
		return Windows
	}
	if runtime.GOOS == "darwin" {
		return Darwin
	}
	if runtime.GOOS == "freebsd" {
		return FreeBSD
	}
	return Linux
}

// GetGOARCH 获取架构信息
func GetGOARCH() string {
	return runtime.GOARCH
}

// GetGOBIN 获取go相关的二进制目录 没有 GOBIN 则找 GOROOT
func GetGOBIN() string {
	out, err := ose.Command("go", "env", "GOBIN").CombinedOutput()
	if err != nil {
		if GetGOOS() == Windows {
			return fmt.Sprintf("%s\\bin", runtime.GOROOT())
		}
		return fmt.Sprintf("%s/bin", runtime.GOROOT())
	}
	outP := strings.Trim(string(out), " \n")
	if outP == "" {
		if GetGOOS() == Windows {
			return fmt.Sprintf("%s\\bin", runtime.GOROOT())
		}
		return fmt.Sprintf("%s/bin", runtime.GOROOT())
	}
	return outP
}

func GetDefaultProtocPATH() string {
	if GetGOOS() == Windows {
		return fmt.Sprintf("%s\\protoc.exe", GetGOBIN())
	}
	return fmt.Sprintf("%s/protoc", GetGOBIN())
}

func WindowsSplit(src string) string {
	return strings.ReplaceAll(src, "/", "\\")
}

func GetFileDir(src string) string {
	return filepath.Dir(src)
}

func Calm2Case(src string) string {
	buffer := new(bytes.Buffer)
	for i, r := range src {
		if unicode.IsUpper(r) {
			if i != 0 {
				buffer.WriteRune('_')
			}
			buffer.WriteRune(unicode.ToLower(r))
		} else {
			buffer.WriteRune(r)
		}
	}
	return buffer.String()
}

// GetWindowsDiskDriverName 获取目录盘符
func GetWindowsDiskDriverName(dir string) string {
	return string([]rune(dir)[0])
}

// FirstUpper 字符串首字母大写
func FirstUpper(s string) string {
	if s == "" {
		return ""
	}
	return strings.ToUpper(s[:1]) + s[1:]
}

// FirstLower 字符串首字母小写
func FirstLower(s string) string {
	if s == "" {
		return ""
	}
	return strings.ToLower(s[:1]) + s[1:]
}

func RFC3339ToTime(value string) (time.Time, error) {
	ts, err := time.Parse(time.RFC3339, value)
	if err != nil {
		return time.Now(), err
	}

	return ts.In(time.Local), nil
}

// Trim 替换windows的换行效果 替换左右的空格
func Trim(src string) string {
	if runtime.GOOS == "windows" {
		src = strings.ReplaceAll(src, "\r\n", "")
		src = strings.ReplaceAll(src, "\n\t", "")
	}
	src = strings.ReplaceAll(src, "\n", "")
	src = strings.ReplaceAll(src, "\t", "")
	src = strings.ReplaceAll(src, "\r", "")
	src = strings.Trim(src, " ")
	return src
}
